package com.huixi.microspur.web.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huixi.microspur.commons.enums.ErrorCodeEnum;
import com.huixi.microspur.web.entity.user.WjUser;
import com.huixi.microspur.web.entity.user.WjUserWx;
import com.huixi.microspur.web.entity.user.WxDecodeUserInfoDTO;
import com.huixi.microspur.web.entity.user.WxSesssionKeyDTO;
import com.huixi.microspur.web.mapper.WjUserMapper;
import com.huixi.microspur.web.service.WjUserService;
import com.huixi.microspur.web.service.WjUserWxService;
import com.huixi.microspur.web.util.RedisUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xzl
 * @since 2020-01-17
 */
@Service
public class WjUserServiceImpl extends ServiceImpl<WjUserMapper, WjUser> implements WjUserService {



    @Value("${weiJu.appId}")
    private String appId;

    @Value("${weiJu.appSecret}")
    private String appSecret;

    @Autowired
    private WjUserService wjUserService;

    @Autowired
    private WjUserWxService wjUserWxService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisUtil redisUtil;




    /**
     *  获取session_key
     * @Author 李辉
     * @Date 2019/11/23 4:31
     * @param code 用户code
     * @return java.lang.String
     **/
    @Override
    public String getWxSessionKey(String code){

        String sessionKeyToUuid = IdUtil.randomUUID();


        StringBuilder result = null;
        try {
            URL url = new URL("https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code" +
                    "=" + code + "&grant_type=authorization_code");

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
            String line = null;
            result = new StringBuilder();
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            connection.disconnect();
        } catch (Exception e) {
            log.error(ErrorCodeEnum.WX000001.msg() + "|" + e.getMessage());
            e.printStackTrace();
        }


        WxSesssionKeyDTO wxSesssionKeyDTO = JSON.parseObject(result.toString(), WxSesssionKeyDTO.class);

        // 放到redis 中存储一个小时 (session_key 本生的有效期就没有多长,估计就两个小时)
        try {
            redisTemplate.opsForValue().set(sessionKeyToUuid, wxSesssionKeyDTO, 1, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error(ErrorCodeEnum.REDIS000001.msg() + "|" + e.getMessage());
        }


        return sessionKeyToUuid;

    }




    /**
     *  获取用户加密信息 并且保存
     * @Author 李辉
     * @Date 2019/11/23 4:33
     * @param
     * @return void
     **/
    @Override
    public WjUser getEncryptionUserInfo(String encryptedData, String session_key, String ivKey) {
        byte[] encode = Base64.decode(encryptedData);
        byte[] aeskey = Base64.decode(session_key);
        byte[] iv = Base64.decode(ivKey);

        String result = null;

        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (aeskey.length % base != 0) {
                int groups = aeskey.length / base + (aeskey.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(aeskey, 0, temp, 0, aeskey.length);
                aeskey = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(aeskey, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(iv));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(encode);
            if (null != resultByte && resultByte.length > 0) {
                result = new String(resultByte, "UTF-8");
                System.out.println(result);
            }
        } catch (Exception e) {
            log.error(ErrorCodeEnum.USER004.msg() +"|"+ e.getMessage());
        }

        WxDecodeUserInfoDTO wxDecodeUserInfoDTO = JSON.parseObject(result, WxDecodeUserInfoDTO.class);

        // 统一的UUID
        String uuid = UUID.randomUUID().toString().replaceAll("-","");

        // 统一的创建时间
        LocalDateTime createDate = LocalDateTime.now();


        // 存到用户 表
        WjUser wjUser = new WjUser();

        // 用户id
        wjUser.setUserId(uuid);
        // 用户名称
        wjUser.setNickName(wxDecodeUserInfoDTO.getNickName());
        // 头像URL地址
        wjUser.setHeadPortrait(wxDecodeUserInfoDTO.getAvatarUrl());
        // 性别
        wjUser.setSex(wxDecodeUserInfoDTO.getGender());
        wjUser.setSignature("快乐源于分享");
        wjUser.setIntroduce("欢迎各位 start");
        // 创建人
        wjUser.setCreateBy(uuid);
        // 创建时间
        wjUser.setCreateTime(createDate);

        boolean save = save(wjUser);


        // 解密后也存入专门存放用户openid 等等的消息的表
        WjUserWx wjUserWx = new WjUserWx();
        wjUserWx.setUserId(uuid);
        wjUserWx.setWxOpenId(wxDecodeUserInfoDTO.getOpenId());
        wjUserWx.setWxUnionId(wxDecodeUserInfoDTO.getUnionId());
        wjUserWx.setWxAppId(wxDecodeUserInfoDTO.getWatermark().getAppid());
        boolean save1 = wjUserWxService.save(wjUserWx);


        return wjUser;


    }




    /**
     *  根据用户code 获取用户的 openId 和 sessionKey , 来确定有没有授权过。
     * @Author 叶秋
     * @Date 2020/2/1 20:17
     * @param code 用户小程序的code
     * @return com.huixi.microspur.web.entity.user.WxSesssionKeyDTO
     **/
    @Override
    public WxSesssionKeyDTO detectionUserAuthorization(String code){



        StringBuilder result = null;
        try {
            URL url = new URL("https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code" +
                    "=" + code + "&grant_type=authorization_code");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
            String line = null;
            result = new StringBuilder();
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }


        WxSesssionKeyDTO wxSesssionKeyDTO = JSON.parseObject(result.toString(), WxSesssionKeyDTO.class);


        return wxSesssionKeyDTO;


    }

}
